//    Copyright (C) Kherty.  All rights reserved.
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Text;
using OpenLS.Spreadsheet.Functions;

namespace OpenLS.Spreadsheet.Expressions
{
    class FunctionInvokeExpression
        : Expression
    {
        readonly SpreadsheetContext _context;
        public override string ToString()
        {
            return this.Function.Name + "(" +
                   string.Join(",",
                              Enumerable.ToArray( Enumerable.Select(this.Arguments, a => a.ToString()))) + ")";
        }
        public FunctionInvokeExpression(Function fn, List<Expression> arguments, SpreadsheetContext context)
        {
            this._context = context;
            _function = fn;
            Contract.Assert(_function != null);
            this.arguments = arguments;
        }
        public override IEnumerable<Expression> GetSubExpressions()
        {
            foreach (Expression e in arguments)
                yield return e;
        }
        internal override Expression Transposed(Cell target)
        {
            return new FunctionInvokeExpression(_function, Enumerable.ToList(Enumerable.Select(arguments, e => e.Transposed(target))), _context);
        }

        public override Expression Offset(CellRelativeAddress a)
        {
            List<Expression> l = new List<Expression>();
            foreach (Expression exp in arguments)
                l.Add(exp.Offset(a));
            return new FunctionInvokeExpression(_function, l, _context);
        }
        public override IEnumerable<IDependencyNode> GetPrecedents(EvaluationContext context)
        {
            if (_function.NoValueAccess)
                yield break;
            foreach (Expression exp in arguments)
            {
                foreach (IDependencyNode c in exp.GetPrecedents(context))
                    yield return c;
            }
        }

        readonly Function _function;
        public override string GetText(TextContext context)
        {
                StringBuilder result = new StringBuilder();
                string n = _function.Name;
                n = context.GetName(n);
                result.Append(n);
                result.Append('(');
                for (int i = 0; i < arguments.Count; i++)
                {
                    result.Append(arguments[i].GetText(context));
                    if (i < arguments.Count - 1)
                        result.Append(context.FormulaArgumentSeparator);

                }
                result.Append(')');
                return result.ToString();
            
        }

        private readonly List<Expression> arguments;
        public List<Expression> Arguments
        {
            get { return arguments; }
        }
        public Function Function { get { return _function; } }
        protected override object GetObjectImp(EvaluationContext context)
        {
            return _function.Invoke(context, arguments);
/*            object[] parms = new object[parameters.Count];
            for (int i = 0; i < parms.Length; i++)
                parms[i] = parameters[i].GetValue(caller);
            return function.InvokeOld(caller, parms);
  */      }

    }
}
